#include "test_tcfixedringbuffer_functional.h"

using namespace PILO::Core::Memory;
static INT32 g_id = 0;

static INT32 test_TCFixedRingBuffer_Constructor(void * param);
static INT32 test_TCFixedRingBuffer_write(void* param);
static INT32 test_TCFixedRingBuffer_read(void* param);
static INT32 test_TCFixedRingBuffer_attach(void* param);
static INT32 test_TCFixedRingBuffer_peek(void* param);

static case_testing_t g_cases_TCFixedBuffer[] = {
    {1, "TCFixedRingBuffer constructor",                0, test_TCFixedRingBuffer_Constructor,               -1},
    {2, "write()                      ",                0, test_TCFixedRingBuffer_write,                     -1},
    {3, "read()                       ",                0, test_TCFixedRingBuffer_read,                      -1},
    {4, "peek()                       ",                0, test_TCFixedRingBuffer_peek,                      -1},
    {5, "attach()                     ",                0, test_TCFixedRingBuffer_attach,                    -1},
};

//-------------------------------------------------- cases -------------------------------------------------------
INT32 test_TCFixedRingBuffer_Constructor(void * )
{
    int rc;
    TCFixedRingBuffer<char, 256> rBuffer_0;
    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 0,MC_INVALID_SIZE , 0, 0, 256)) != 0) {
        return -rc;
    }

    BOOL isExp = FALSE;
    try {
        TCFixedRingBuffer<char, 4097> erBuffer_0;
    } catch (INT32 e) {
        if (e == EC_REACH_UPPER_LIMIT) {
            isExp = TRUE;       
        }
    }
    if (isExp == FALSE) {
        return -10;
    }
    
    TCFixedRingBuffer<TestElement, 256> rBuffer_1;
    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 0,MC_INVALID_SIZE , 0, 0, 256)) != 0) {
        return (-100)+rc;
    }

    isExp = FALSE;
    try {
        TCFixedRingBuffer<TestElement, 4097> erBuffer_0;
    } catch (INT32 e) {
        if (e == EC_REACH_UPPER_LIMIT) {
            isExp = TRUE;       
        }
    }
    if (isExp == FALSE) {
        return -10;
    }

    return 0;
}

INT32 test_TCFixedRingBuffer_write( void*  )
{
    int rc;

    TCFixedRingBuffer<char, 256> rBuffer_0;
    char sampleBuffer[256];
    for (int i = 0; i<sizeof(sampleBuffer); i ++) {
        sampleBuffer[i] = (char)i;
    }

    if (53 != rBuffer_0.write(sampleBuffer, 53)) {
        return -1;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 53,0 , 53, 53, 203)) != 0) {
        return -2;
    }

    if (rBuffer_0.write(sampleBuffer, 203 + 1, EnumNoopOnPartial) != MC_INVALID_SIZE) {
        return -3;
    }

    if (203 != rBuffer_0.write(sampleBuffer+53, 203)) {
        return -4;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 256,0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -5;
    }

    for (int i = 0; i<sizeof(sampleBuffer); i ++) {
        if (sampleBuffer[i] != rBuffer_0.internalBuffer()[i]) {
            return -6;
        }
    }

    if (0 != rBuffer_0.write(sampleBuffer, 1)) {
        return -7;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 256,0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -8;
    }

    char buffer[256];
    if (120 != rBuffer_0.read(buffer, 120)) {
        return -9;
    }
    
    for (int i = 0; i < 120; i ++) {
        if (buffer[i] != i) {
            return -10;
        }
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 136,120 , 136, 0, 120)) != 0) {
        return -11;
    }

    if (100 != rBuffer_0.write(sampleBuffer, 100)) {
        return -12;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 236,120 , 236, 100, 20)) != 0) {
        return -13;
    }

    //complex objects
    TCFixedRingBuffer<TestElement, 256> rBuffer_1;
    TestElement sampleBuffer1[256];
    for (int i = 0; i<256; i ++) {
        sampleBuffer1[i].setID(i);
        sampleBuffer1[i].setData(i);
    }

    if (53 != rBuffer_1.write(sampleBuffer1, 53)) {
        return -101;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 53 * sizeof(TestElement), 0 , 53, 53, 203)) != 0) {
        return -102;
    }

    if (rBuffer_1.write(sampleBuffer1, 203 + 1, Buffer::EnumNoopOnPartial) != MC_INVALID_SIZE) {
        return -103;
    }

    if (203 != rBuffer_1.write(sampleBuffer1 + 53, 203)) {
        return -104;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement),0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -105;
    }

    for (int i = 0; i<sizeof(sampleBuffer1)/sizeof(TestElement); i ++) {
        if (sampleBuffer1[i] != rBuffer_1.internalBuffer()[i]) {
            return -106;
        }
    }

    if (0 != rBuffer_1.write(sampleBuffer1, 1)) {
        return -107;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement), 0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -108;
    }

    TestElement buffer2[256];
    if (120 != rBuffer_1.read(buffer2, 120)) {
        return -109;
    }

    for (int i = 0; i < 120; i ++) {
        if (buffer2[i].id() != i) {
            return -110;
        }
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 136 * sizeof(TestElement),120 , 136, 0, 120)) != 0) {
        return -111;
    }

    if (100 != rBuffer_1.write(sampleBuffer1, 100)) {
        return -112;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 236 * sizeof(TestElement),120 , 236, 100, 20)) != 0) {
        return -113;
    }

    return 0;
}

INT32 test_TCFixedRingBuffer_read( void*  )
{
    char    buffer[256];
    TCFixedRingBuffer<char, 256>   rBuffer;
    if (0 != rBuffer.read(buffer, 257)) {
        return -1;
    }
    for (int i = 0; i < 256; i ++) {
        buffer[i] = (char)i;
    }
    if (140 != rBuffer.write(buffer, 140)) {
        return -2;
    }
    if (0 != ValidateBufferObjectInformation(rBuffer, 256, 140, 0, 140, 140, 116)) {
        return -3;
    }
    memset(buffer, 0x00, 140);
    if (MC_INVALID_SIZE != rBuffer.read(buffer, 141, Buffer::EnumNoopOnPartial)) {
        return -4;
    }
    if (0 != ValidateBufferObjectInformation(rBuffer, 256, 140, 0, 140, 140, 116)) {
        return -5;
    }
    if (140 != rBuffer.read(buffer, 140, Buffer::EnumNoopOnPartial)) {
        return -6;
    }
    for (int i = 0; i < 256; i ++) {
        if ((BYTE) buffer[i] != i) {
            return -7;
        }
    }
    if (0 != ValidateBufferObjectInformation(rBuffer, 256, 0, MC_INVALID_SIZE, 0, 140, 256)) {
        return -8;
    }

    if (256 != rBuffer.write(buffer, 256)) {
        return -9;
    }
    memset(buffer, 0x00, 256);
    if (256 != rBuffer.read(buffer, 256, Buffer::EnumNoopOnPartial)) {
        return -10;
    }
    for (int i = 0; i < 256; i ++) {
        if ((BYTE) buffer[i] != i) {
            return -11;
        }
    }

    //complex objects
    TestElement    buffer1[256];
    TCFixedRingBuffer<TestElement, 256>   rBuffer1;
    if (0 != rBuffer.read(buffer, 257)) {
        return -101;
    }
    for (int i = 0; i < 256; i ++) {
        buffer1[i].setID(i);
        buffer1[i].setData(i);
    }
    if (140 != rBuffer1.write(buffer1, 140)) {
        return -102;
    }
    if (0 != ValidateBufferObjectInformation(rBuffer1, 256, 140 * sizeof(TestElement), 0, 140, 140, 116)) {
        return -103;
    }
    memset(buffer1, 0x00, 140 * sizeof(TestElement));
    if (MC_INVALID_SIZE != rBuffer1.read(buffer1, 141, Buffer::EnumNoopOnPartial)) {
        return -104;
    }
    if (0 != ValidateBufferObjectInformation(rBuffer1, 256, 140 * sizeof(TestElement), 0, 140, 140, 116)) {
        return -105;
    }
    if (140 != rBuffer1.read(buffer1, 140, Buffer::EnumNoopOnPartial)) {
        return -106;
    }
    for (int i = 0; i < 256; i ++) {
        if (buffer1[i].id() != i) {
            return -107;
        }
    }
    if (0 != ValidateBufferObjectInformation(rBuffer1, 256, 0, MC_INVALID_SIZE, 0, 140, 256)) {
        return -108;
    }
    if (256 != rBuffer1.write(buffer1, 256)) {
        return -109;
    }
    memset(buffer1, 0x00, 256 * sizeof(TestElement));
    if (256 != rBuffer1.read(buffer1, 256, Buffer::EnumNoopOnPartial)) {
        return -110;
    }
    for (int i = 0; i < 256; i ++) {
        if (buffer1[i].id() != i) {
            return -111;
        }
    }

    return 0;
}

INT32 test_TCFixedRingBuffer_peek( void*  )
{
    TCFixedRingBuffer<char, 256> rBuffer_0;

    char sampleBuffer[256];
    for (int i = 0; i<sizeof(sampleBuffer); i ++) {
        sampleBuffer[i] = (char)i;
    }

    if (256 != rBuffer_0.write(sampleBuffer, 256)) {
        return -1;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_0, 256, 256, 0, 256, MC_INVALID_SIZE, 0)) {
        return -2;
    }

    char buffer[256];
    if (100 != rBuffer_0.peek(buffer, 100)) {
        return -3;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_0, 256, 256, 0, 256, MC_INVALID_SIZE, 0)) {
        return -4;
    }

    if (MC_INVALID_SIZE != rBuffer_0.peek(buffer, 257, Buffer::EnumNoopOnPartial)) {
        return -5;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_0, 256, 256, 0, 256, MC_INVALID_SIZE, 0)) {
        return -6;
    }

    // complex objects
    TCFixedRingBuffer<TestElement, 256> rBuffer_1;
    TestElement sampleBuffer1[256];
    for (int i = 0; i < 256; i ++) {
        sampleBuffer1[i].setID(i);
        sampleBuffer1[i].setData(i);
    }

    if (256 != rBuffer_1.write(sampleBuffer1, 256)) {
        return -101;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement), 0, 256, MC_INVALID_SIZE, 0)) {
        return -102;
    }

    TestElement buffer2[256];
    if (100 != rBuffer_1.peek(buffer2, 100)) {
        return -103;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement), 0, 256, MC_INVALID_SIZE, 0)) {
        return -104;
    }

    if (MC_INVALID_SIZE != rBuffer_1.peek(buffer2, 257, Buffer::EnumNoopOnPartial)) {
        return -105;
    }

    if (0 !=ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement), 0, 256, MC_INVALID_SIZE, 0)) {
        return -106;
    }

    return 0;

}



INT32 test_TCFixedRingBuffer_attach( void*  )
{
    int rc;

    char attBuffer0[300];
    TCFixedRingBuffer<char, 256> rBuffer_0;
    rBuffer_0.attach(attBuffer0, 256, 0, 0);


    char sampleBuffer[256];
    for (int i = 0; i<sizeof(sampleBuffer); i ++) {
        sampleBuffer[i] = (char)i;
    }

    if (53 != rBuffer_0.write(sampleBuffer, 53)) {
        return -1;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 53,0 , 53, 53, 203)) != 0) {
        return -2;
    }

    if (rBuffer_0.write(sampleBuffer, 203 + 1, Buffer::EnumNoopOnPartial) != MC_INVALID_SIZE) {
        return -3;
    }

    if (203 != rBuffer_0.write(sampleBuffer+53, 203)) {
        return -4;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 256,0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -5;
    }

    for (int i = 0; i<sizeof(sampleBuffer); i ++) {
        if (sampleBuffer[i] != rBuffer_0.internalBuffer()[i]) {
            return -6;
        }
    }

    if (0 != rBuffer_0.write(sampleBuffer, 1)) {
        return -7;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 256,0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -8;
    }

    char buffer[256];
    if (120 != rBuffer_0.read(buffer, 120)) {
        return -9;
    }

    for (int i = 0; i < 120; i ++) {
        if (buffer[i] != i) {
            return -10;
        }
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 136,120 , 136, 0, 120)) != 0) {
        return -11;
    }

    if (100 != rBuffer_0.write(sampleBuffer, 100)) {
        return -12;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_0, 256, 236,120 , 236, 100, 20)) != 0) {
        return -13;
    }

    //complex objects

    TestElement attBuffer1[258];
    TCFixedRingBuffer<TestElement, 256> rBuffer_1;
    rBuffer_1.attach(attBuffer1, 256, 0, 0);
    TestElement sampleBuffer1[256];
    for (int i = 0; i<256; i ++) {
        sampleBuffer1[i].setID(i);
        sampleBuffer1[i].setData(i);
    }

    if (53 != rBuffer_1.write(sampleBuffer1, 53)) {
        return -101;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 53 * sizeof(TestElement), 0 , 53, 53, 203)) != 0) {
        return -102;
    }

    if (rBuffer_1.write(sampleBuffer1, 203 + 1, Buffer::EnumNoopOnPartial) != MC_INVALID_SIZE) {
        return -103;
    }

    if (203 != rBuffer_1.write(sampleBuffer1 + 53, 203)) {
        return -104;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement),0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -105;
    }

    for (int i = 0; i<sizeof(sampleBuffer1)/sizeof(TestElement); i ++) {
        if (sampleBuffer1[i] != rBuffer_1.internalBuffer()[i]) {
            return -106;
        }
    }

    if (0 != rBuffer_1.write(sampleBuffer1, 1)) {
        return -107;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 256 * sizeof(TestElement), 0 , 256, MC_INVALID_SIZE, 0)) != 0) {
        return -108;
    }

    TestElement buffer2[256];
    if (120 != rBuffer_1.read(buffer2, 120)) {
        return -109;
    }

    for (int i = 0; i < 120; i ++) {
        if (buffer2[i].id() != i) {
            return -110;
        }
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 136 * sizeof(TestElement),120 , 136, 0, 120)) != 0) {
        return -111;
    }

    if (100 != rBuffer_1.write(sampleBuffer1, 100)) {
        return -112;
    }

    if ((rc = ValidateBufferObjectInformation(rBuffer_1, 256, 236 * sizeof(TestElement),120 , 236, 100, 20)) != 0) {
        return -113;
    }

    return 0;
}



//------------------------------------------- main test function -------------------------------------------------

INT32 testTCFixedRingBufferFunctional(INT32 id, int breakOnErrorOccured)
{
    g_id = id;

    FormatOutputToConsole("Testing Part_%d <tcfixedringbuffer.h>\n", id);

    int i=0;
    for (i=0; i<MCF_COUNT_OF(g_cases_TCFixedBuffer); i++) {
        case_testing_t * caseParam = &g_cases_TCFixedBuffer[i];
        ASSERT(caseParam != NULL);
        FormatOutputToConsole(" #[%03d.%03d]: Testing %s \t",g_id, caseParam->ct_id, caseParam->ct_decription);

        caseParam->ct_result = caseParam->ct_function(static_cast<case_testing_t *>(caseParam));
        if (caseParam->ct_result == 0) { //ok
            FormatOutputToConsole("[PASSED]\n");
        } else {
            FormatOutputToConsole("[FAILED:%d]\n",caseParam->ct_result);
            if (breakOnErrorOccured) {
                ASSERT(FALSE);
            }
        }
    }


    FormatOutputToConsole("Result of Part_%d <tcfixedringbuffer.h/cpp> total  %d, failed %d\n\n",id, MCF_COUNT_OF(g_cases_TCFixedBuffer), failedOFCases(g_cases_TCFixedBuffer,MCF_COUNT_OF(g_cases_TCFixedBuffer)));
    return 0;
}

